﻿#include <iostream>
#include <string>
#include <assert.h>
/* glad必须先包含，后包含glfw */
#include "glad/glad.h"
#include "glfw/glfw3.h"
#include "checkError.h"
#include "Application.h"

// 声明且实现窗体变化回调
void OnResze(int width, int height)
{
  std::cout << "窗体最新大小：" << width << " " << height << std::endl;
  GL_CALL(glViewport(0, 0, width, height));
}

void OnKey(int key, int scancode,  int action, int mods)
{
  std::cout << "key：" << key << std::endl;
}

void prepareVBO()
{
  // 1 创建一个vbo /*还没有真能正分配显存*/
  GLuint vbo = 0;
  GL_CALL(glGenBuffers(1, &vbo));
  // 2 销毁一个vbo
  GL_CALL(glDeleteBuffers(1, &vbo));
  // 3 创建n个vbo
  GLuint vboArr[] = { 0,0,0 };
  GL_CALL(glGenBuffers(3, vboArr));
  // 4 销毁n个vbo
  GL_CALL(glDeleteBuffers(sizeof(vboArr), vboArr));
}

void prepare()
{
  float vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
  };
  // 1 生成一个vbo
  GLuint vbo = 0;
  GL_CALL(glGenBuffers(1, &vbo));
  // 2 绑定当前vbo，到opengl状态机的当前vbo插槽
  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo));
  // 3 向当前vbo传输数据
  GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
}

void prepareSingleBuffer()
{
  float positions[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
  };

  float colors[] = {
    1.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f,  0.0f, 1.0f
  };
  // 1 生成一个vbo
  GLuint vboPos = 0, vboColor = 0;
  GL_CALL(glGenBuffers(1, &vboPos));
  GL_CALL(glGenBuffers(1, &vboColor));

  // 2 绑定当前vbo，到opengl状态机的当前vbo插槽
  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vboPos));
  GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW));

  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vboColor));
  GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW));

  // 创建及绑定vao
  GLuint vaoPos = 0;
  GL_CALL(glGenVertexArrays(1, &vaoPos));
  GL_CALL(glBindVertexArray(vaoPos));
  // 描述为指数型
  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vboPos)); // 只有绑定了vbo，下面的属性描述才会有当前vbo有关系
  GL_CALL(glEnableVertexAttribArray(0));
  GL_CALL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0));

  // 创建及绑定vao
  GLuint vaoColor = 0;
  GL_CALL(glGenVertexArrays(1, &vaoColor));
  GL_CALL(glBindVertexArray(vaoColor));
  // 描述为指数型
  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vboColor)); // 只有绑定了vbo，下面的属性描述才会有当前vbo有关系
  GL_CALL(glEnableVertexAttribArray(1));
  GL_CALL(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (GLvoid*)0));

  GL_CALL(glBindVertexArray(0));
}

void prepareInterleavedBuffer()
{
  float vertices[] = {
    -0.5f, -0.5f, 0.0f,1.0f, 0.0f, 0.0f,
     0.5f, -0.5f, 0.0f,0.0f, 1.0f, 0.0f,
     0.0f,  0.5f, 0.0f,0.0f,  0.0f, 1.0f
  };

  GLuint vbo = 0;
  GL_CALL(glGenBuffers(1, &vbo));
  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo));
  GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));

  GLuint vao = 0;
  GL_CALL(glGenVertexArrays(1, &vao));
  GL_CALL(glBindVertexArray(vao));

  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo));

  GL_CALL(glEnableVertexAttribArray(0));
  GL_CALL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GL_FLOAT), (void*)0));

  GL_CALL(glEnableVertexAttribArray(1));
  GL_CALL(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GL_FLOAT), (void*)(3 * sizeof(GL_FLOAT))));

  GL_CALL(glBindVertexArray(0));
}


int main()
{
  
  if (!app->init(800, 600))
  {
    return -1;
  }

  // 设置窗口回调
  app->setResizeCallback(OnResze);
  app->setKeyboardCallback(OnKey);

  /* 设置opengl视口以及清理颜色 */
  GL_CALL(glViewport(0, 0, 800, 600));
  GL_CALL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f));

  prepareInterleavedBuffer();

  // 3 执行窗体循环
  while (app->update())
  {
    // 执行opengl画布清理操作
    glClear(GL_COLOR_BUFFER_BIT);
  }

  // 4 退出程序前清理
  app->destroy();
  return 0;
}